<?

	//modal('workers?filter=id:10;name:haloworld');
	
	class c_storage_controller extends c_base_controller
	{
		function __construct($id_or_name = '', $params = array())
		{
			global $mvc;
			
			parent::__construct();
			
			// Если имя определено, то заполним данные хранилища.
			if ($id_or_name)
				$this->create($id_or_name, $params);
		}
	
		// Показать список view.
		function index($args)
		{
			global $mvc;

			//$this->show('dialogs');

			$mvc->theme->set_item('header', 'admin_header');
			$mvc->theme->set_item('footer', 'admin_footer');
			
			return $this->_index($args);
		}
		
		// Скрытый метод невидимый снаружи.
		function _index($args)
		{
			global $mvc;
			$this->args = $args;
			// Список таблиц.
			// $tables = $mvc->db->list_tables('stor', 'name');

			$this->view_name = isset($this->args['view']) ? mysql_escape_string($this->args['view']) : '';
			if (!$this->view_name) $this->view_name ='view_list';
			$view_name = $this->view_name;
		
			// Получение команды.
			$cmd = isset($this->args['cmd']) ? $this->args['cmd'] : '';
			if (isset($this->args['_cmdset'])) $cmd = 'set';
			if (isset($this->args['_cmdback'])) $cmd = 'back';
			if (isset($this->args['_cmddel'])) $cmd = 'del';
			if (isset($this->args['_cmdcopy'])) $cmd = 'copy';
			
			$filter = isset($this->args['_filter']) ? mysql_escape_string($this->args['_filter']) : '';
		
			$next_view = $view_name; // Какой view показывать после данного.
		
			$this->create($view_name);			
	
			if ($cmd != '')
			{
				$contr = $this;//new MVCController($view_name);
		
				if ($cmd == 'set')
				{
					$data = $contr->extract_data($this->args, $mvc->db->get_fields($this->params['table_name']));
					$mvc->db->set_data($this->params['table_name'], $data);
					$next_view = $contr->params['next_view'];
				}
				elseif ($cmd == 'del')
				{
					function is_checked($item)
					{
						return (int)$item;
					}
					$data = $mvc->extract_data($this->args, '/^_checked_(\\d*)$/');
					$data = array_filter($data, 'is_checked');
					$data = array_keys($data);			
					
					$mvc->db->del_data($this->params['table_name'], $data);					
					echo ('<font color="red">Needs test</font>');
				}
				elseif ($cmd == 'copy')
				{
					$data = $contr->extract_data($this->args, $mvc->db->get_fields($this->params['table_name']));
					$data = array(current($data));
					$data[0]['id'] = 0;
						$contr->set_data($data);
					$next_view = $contr->params['next_view'];
				}
				elseif ($cmd == 'back')
				{
					$next_view = $contr->params['prev_view'];
				}
				elseif ($cmd == 'create_view_list')
				{
					$table_name = $this->args['table_name'];
					$contr->_create_view_list($table_name);
				}
				elseif ($cmd == 'create_view_item')
				{
					$table_name = $this->args['table_name'];
					$contr->_create_view_item($table_name);
				}
				elseif ($cmd == 'create_views')
				{
					$table_name = $this->args['table_name_'];
					$contr->_create_view_item($table_name);
					$contr->_create_view_list($table_name);
				}
			}


			//echo ' <b>[view:'.$view_name.']</b> ';
			//echo ' <b>[next_view:'.$next_view.']</b> ';
			//echo ' <b>[cmd:'.$cmd.']</b> ';
			
			// TODO: Переопределить View по умолчанию для каждого пользователя.			
			
			$this->create($next_view);
			echo $this->render();
			//$mvc->bm->add('finished');
			//include ($mvc->view_path.'bm_default.php');//<pre>'.print_r($mvc->bm->points, true);
		}

		
		

		
		function index2($args)
		{
			global $mvc;
			$sql = $mvc->parse('SELECT * FROM {dbpref}views WHERE id='.(int)$args[2].' OR view_name="'.mysql_escape_string($args[2]).'"');	
			$this->params = $mvc->db->get_data($sql, true);
			
			$page = (int)$args[3];
			
			$this->paged_data = $mvc->db->get_data_paged($this->params['view_sql'], 5, $page);
			$this->data = $this->paged_data['data'];
			
			//print_r($this->paged_data);
			
			//print_r($this->params['tpl2']);

			//print($this->params['tpl2']);
			eval('?>'.$this->params['tpl2']);
			
			die();
			

			echo '<pre>';
						
			$data = $mvc->db->get_data($this->params['view_sql']);
			
			if (sizeof($data) > 0)
			{
				echo '<table border="1">';
				echo '<tr>';
				foreach($data[0] as $key => $field)
				{
							echo '<th>'.$key.'</th>';				
				}
				echo '</tr>';
				
				foreach ($data as $row)
				{
					echo '<tr>';
						foreach($row as $key => $field)
						{
							echo '<td>';
							echo $field;
							echo '</td>';
						}
					echo '</tr>';
				}
			}
			else
			{
				echo 'No data avaliable';
			}
			
			//print_r($data);
			
			//print_r($this->data['view_sql']);
			
			//print_r($this->data);
		}

// ----------------------  Вставлено из mvc_view --------------------

		function create($id_or_name, $params = array(), $uid = '')
		{
			global $mvc;
		
			// Получить параметры нужного view.
			$sql = $mvc->parse('SELECT * FROM {dbpref}views WHERE id="'.$id_or_name.'" OR view_name="'.$id_or_name.'"');	
			$this->params = $mvc->db->get_data($sql, true);
			// Дополняем данные.
			$this->params['uid'] = $uid;//'s'.rand(1000, 9999);
			$this->params['database'] = $mvc->config['dbname'];
			//$this->params['view_id'] = $this->params['id'];
			$this->params['rowid'] = (int)$this->args['rowid']; // Получить id строки (если есть).
			$this->page = (int)$this->args['page'.$this->params['uid']]; // Получить текущую страницу, если она есть.			
			// Дополняем поданными данными.
			$this->params = array_merge($this->params, $params);			
			// Создаем таблицу.
			$this->table = new c_table_model($this->params['table_name']);
		}	
		
		// Рендерит текущий view.
		function render($tpl = '', $data = NULL)
		{
			global $mvc;
			
			$mvc->bm->add('p1');
			
			$sql = $this->parse($this->params['view_sql']);

			$row_blocks = array(); // Шаблоны вставок строк таблиц (eachrow).
			
			if ($tpl == '')
				$html = $this->params['tpl'];
			else
				$html = $tpl;						
			
			//$ins = new c_insertion_util();
			//$ins->debug = true;
			//$ins->setVar('comment', 'comcommment');
			//$ins->setVar('something', 'comsomething');
			//$ins->insertions['eachfield'] = array($this, 'func');
			/* '<? $this->setVar("something", "comsomething"); echo $this->parse($this->v("comment")); ?>'; //array($this, 'func'); */
			//echo $ins->parse('<<eachfield: comment=`<{something}> <{i}>`>>');//$html);
			//echo '<pre>';
			//print_r($mvc->messages);
			//die();
			
			// --- Выделение вставок для данных таблицы {eachrow}.
			$i = strpos($html, '{eachrow}');
			while ($i !== false)
			{
				$j = strpos($html, '{/eachrow}', $i);
				$row_block = substr($html, $i + strlen('{eachrow}'), $j - $i - strlen('{eachrow}'));
				$html = substr($html, 0, $i).'|_subfield'.sizeof($row_blocks).'_|'.substr($html, $j + strlen('{/eachrow}'));
				array_push($row_blocks, $row_block);
				$i = strpos($html, '{eachrow}');
			}
			
			$html = $this->parse($html, 0); // Первый проход, для общего рендера.			

			// --- Парсинг блоков с данными таблицы.
			$row_data = array();
			$sql = $this->parse($this->params['view_sql']);			
			
			// Обрезание для постраничного вывода.
			if ($this->page_size > 0)
				$sql .= ' limit '.$this->page_size*$this->page.','.$this->page_size;

			if ($data == NULL)
			{
				$data = array();				
				$r = $mvc->db->query($sql);
				
				if ($r)
				{				
					// Если данных нет и разрешено добавлять пустую строку, то создадим ее по полям.
					if ((mysql_num_rows($r) == 0) && $this->params['allow_empty'])
					{
						$data[0] = array();
						for($i = 0; $i < mysql_num_fields($r); $i++)
							$data[0][mysql_field_name($r, $i)] = '';
					}
					
					// Просто пробегаем по записям и рендерим их.
					else
					{
						while($a = mysql_fetch_assoc($r))
							array_push($data, $a);
					}
					mysql_free_result($r);
				}
			}
			
			for($i = 0; $i < sizeof($data); $i++)
			{
				foreach($row_blocks as $k => $row_block)
				{
					$a['i'] = $i;
					$row_block = $this->parse($row_block, $data[$i]);
					//echo '<pre>';
					
					//print_r($this->parse($row_block, $data[$i]));
					//print_r($row_block);
					//die();
					$row_data[$k] .= $row_block;
				}
			}
			
			// --- Вставка блоков с данными таблицы.
			foreach($row_data as $k => $data)
			{
				$html = str_replace('|_subrow'.$k.'_|', $data, $html);
			}
			
			// --- Вставка блоков с данными по полям.
			foreach($row_data as $k => $data)
			{
				$html = str_replace('|_subfield'.$k.'_|', $data, $html);
			}

			$html = str_replace('|_subfield0_|', '', $html);
			
			//$mvc->bm->add('p2');
			//echo '<pre>';
			//print_r($mvc->bm->points);
			//echo $this->params['view_sql'];
			
			//die();

			return $html;			
		}
		
		// Вставка. Выполнение запроса.
		function sql($params, $parser)
		{
			global $mvc;
			$i = 0;
			$r = $mvc->db->query($params['query']);
			while($a = mysql_fetch_assoc($r))
			{
				//if ($i++ > 40)
				{
					$parser->set_var('row', $a);
					print($parser->parse($params['tpl']));
					//if ($i++ > 250)
					{
						//$mvc->bm->add('endendend');
						//print_r($mvc->bm->points);
						//die();
					}
				}
			}
			mysql_free_result($r);
			return '';
		}
		
		// Вставка. Поля таблицы.
		function fields($params, $parser)
		{
			global $mvc;
			$html = '';
			foreach($this->table->fields as $field)
			{
				//$html .= ;
				$parser->set_var('field', $field);
				$html .= '<hr color="green">'.$parser->parse($params['tpl']);
			}
			return $html;
		}
		
		function eachrow($params, $parser)
		{
			foreach($this->data as $row)
			{
				$parser->set_var('row', $row);
				echo $parser->parse($params['tpl']);
			}
		}
		
		function edit($args)
		{
			global $mvc;
			
			echo '<pre>';
			$this->create($args[2]);
			print_r($this->params);
			
			
			
			
			
			//print_r($args[2]);
			
		
		
			//$fcomment = '*&%&A^SDJ';
			/*
			// Описание поля.
			if ($fname)
			{
				$fcomment = isset($this->table->fields[$fname]) ? $this->table->fields[$fname]['comment'] : '';
				if (!$fcomment) $fcomment = $fname;
			}
			else // Поле не задано - описание таблицы.
			{
				$fcomment = isset($this->table) ? $this->table->comment : '';
				if (!$fcomment) $fcomment = $this->table->name;
			}
			*/
			//$fname = $params['f'];
			//$fullfname = $fname.'_'.$params['_parent']['row']['id']; // Полное уникальное имя поля.			
			//$fvalue = $params['_parent']['row'][$params['f']];
			//echo '<input type="text" name="'.$fullfname.'" value="'.$fvalue.'" class="'.$params['class'].'">';
		}
		
		function checked($params, $parser)
		{
			$item_name = '_checked_'.$params['_parent']['row']['id'];
			echo '<input type="hidden" name="'.$item_name.'" value="0"/>';
			echo '<input type="checkbox" onchange="this.form.elements[\''.$item_name.'\'].value=this.checked?1:0"/>';			
		}
		
		// Рендерит текущий view.
		function render2()
		{		
			global $mvc;
			
			$mvc->bm->add('p1');			
			
			$ins = new c_insertion_util();
			$ins->vars = array_merge($ins->vars, $this->params);
			$ins->insertions['sql'] = array($this, 'sql');
			$ins->insertions['fields'] = array($this, 'fields');
			$ins->insertions['eachrow'] = array($this, 'eachrow');
			$ins->insertions['edit'] = array($this, 'edit');
			$ins->insertions['checked'] = array($this, 'checked');
			
			//$ins->debug = true;
			//my_print_r($ins->parse('<<parseroff>> {{somevalue}} <<parseron>>'));
			//echo '<pre>';
			//print_r($mvc->messages);
			//die();
			
			$mvc->bm->add('p1');
			
			//$sql = $this->parse($this->params['view_sql']);
			//die($this->params['view_sql']);
			$sql = $ins->parse($this->params['view_sql']);
			$this->sql = $sql;
			$html = $this->params['tpl'];
			
			$row_blocks = array(); // Шаблоны вставок строк таблиц (eachrow).
			
			// --- Выделение вставок для данных таблицы {eachrow}.
			$i = strpos($html, '{eachrow}');
			while ($i !== false)
			{
				$j = strpos($html, '{/eachrow}', $i);
				$row_block = substr($html, $i + strlen('{eachrow}'), $j - $i - strlen('{eachrow}'));
				$html = substr($html, 0, $i).'|_subfield'.sizeof($row_blocks).'_|'.substr($html, $j + strlen('{/eachrow}'));
				array_push($row_blocks, $row_block);
				$i = strpos($html, '{eachrow}');
			}
			
			$html = $this->parse($html, 0); // Первый проход, для общего рендера.
			
			// --- Парсинг блоков с данными таблицы.
			$row_data = array();
			//$sql = $this->parse($this->params['view_sql']);			
			
			// Обрезание для постраничного вывода.
			if ($this->page_size > 0)
				$sql .= ' limit '.$this->page_size*$this->page.','.$this->page_size;

			if ($data == NULL)
			{
				$data = array();
				$r = $mvc->db->query($sql);
				
				if ($r)
				{
					// Если данных нет и разрешено добавлять пустую строку, то создадим ее по полям.
					if ((mysql_num_rows($r) == 0) && $this->params['allow_empty'])
					{
						$data[0] = array();
						for($i = 0; $i < mysql_num_fields($r); $i++)
							$data[0][mysql_field_name($r, $i)] = '';
					}
					
					// Просто пробегаем по записям и рендерим их.
					else
					{
						while($a = mysql_fetch_assoc($r))
						{
							array_push($data, $a);
						}
					}
					mysql_free_result($r);
				}
			}
			
			for($i = 0; $i < sizeof($data); $i++)
			{
				foreach($row_blocks as $k => $row_block)
				{
					$a['i'] = $i;
					$row_block = $this->parse($row_block, $data[$i]);
					$row_data[$k] .= $row_block;
				}
			}
			
			// --- Вставка блоков с данными таблицы.
			foreach($row_data as $k => $data)
			{
				$html = str_replace('|_subrow'.$k.'_|', $data, $html);
			}
			
			// --- Вставка блоков с данными по полям.
			foreach($row_data as $k => $data)
			{
				$html = str_replace('|_subfield'.$k.'_|', $data, $html);
			}
			
			$this->data = $mvc->db->get_data($sql);
			$html = $ins->parse($html);
			//$html = $this->parse($html);
			
			//$mvc->bm->add('p2');
			//echo '<pre>';
			//print_r($mvc->bm->points);
			//echo $this->params['view_sql'];
			
			//die();

			return $html;
		}
		
		
		// Обработать строку данных $row, используя шаблон $tpl.
		// $tpl - текст шаблона, $row - ассоц. массив с данными, $no_controls - не рендерить контролы.
		function parse($tpl, $row = 0)
		{
			global $mvc;
			
			if (!$row) $row = array();
			
			ob_start();
			eval('?>'.$tpl);
			$tpl = ob_get_clean();
			
			$vars = array(); // Временный массив для хранения значений полей, чтобы не производить замену параметров внутри них.
			$nextvar = 0;

			// Ищем все вставки вида {something} и пытаемся заменить. Вложение разрешено.
			while($j = strpos($tpl, '}', $j))
			{
				// Поиск соответствующей открывающей скобки.
				$i = $j;
				while (($i > 0) && ($tpl[--$i] != '{'));
				
				// Вырезать найденный блок.
				$sub = substr($tpl, $i + 1, $j - $i - 1);
				
				if (array_key_exists($sub, $row)) // Найдено поле, вернем его значение.
				{					
					$sub = stripslashes($row[$sub]);
				}
				else if (array_key_exists($sub, $this->params)) // Найден параметр, вернем его значение.
				{					
					$sub = $this->params[$sub];					
				}
				elseif (!$this->no_controls) // Видимо, найден контрол, попроруем создать его.
				{
					$parts = explode(':', $sub);
					$fname = $parts[0]; // Имя поля.
					$fullfname = $fname.'_'.$row['id']; // Полное уникальное имя поля.
					$fvalue = $row[$fname]; // Значение поля.
					//echo '<pre>';
					//print_r($parts);
					//echo $fname.'<br>';					
					//print_r($this->table->fields);
					//echo '<hr>';
					//print_r($this->table->fields);
					//print_r($row);
					
					// Описание поля.
					if ($fname)
					{
						$fcomment = isset($this->table->fields[$fname]) ? $this->table->fields[$fname]['comment'] : '';
						if (!$fcomment) $fcomment = $fname;
					}
					else // Поле не задано - описание таблицы.
					{
						$fcomment = isset($this->table) ? $this->table->comment : '';
						if (!$fcomment) $fcomment = $this->table->name;
					}
					
					$args = explode(';', $parts[1]); // Параметры процессора.
					
					if ($args[0] == 'fullname') // Текстовое поле ввода.
					{
						$sub = $fullfname;
					}
					
					elseif ($args[0] == 'comment') // Текстовое поле ввода.
					{
						$sub =  $fcomment;
					}
					
					elseif ($args[0] == 'label') // Запрет редактирования данных.
					{
						// 1. ID контрола.
						$id = ($args[1]) ? 'id="'.$args[1].'"' : '';
						$sub = $fvalue.'<input type="hidden" name="'.$fullfname.'" value="'.$fvalue.'" '.$id.'>';
					}
					
					elseif ($args[0] == 'datepicker') // Запрет редактирования данных.
					{
						// 1. ID контрола.
						$id = ($args[1]) ? 'id="'.$args[1].'"' : '';
						$sub = '<input type="text" class="datepicker" name="'.$fullfname.'" value="'.$fvalue.'" '.$id.'>';
					}					
					
					elseif ($args[0] == 'edit') // Текстовое поле ввода.
					{
						// 1. ID контрола. 
						$id = ($args[1]) ? 'id="'.$args[1].'"' : '';
						$sub = '<input type="text" name="'.$fullfname.'" value="'.$fvalue.'" '.$id.'>';
					}
					
					elseif ($args[0] == 'textedit') // Многострочное поле ввода textarea.
					{
						// 1. ID контрола. 
						$id = ($args[1]) ? 'id="'.$args[1].'"' : '';
						$sub = '<textarea name="'.$fullfname.'" '.$id.'>'.$fvalue.'</textarea>';
					}
					
					elseif ($args[0] == 'tinymce') // Поле редактирования текста TinyMCE.
					{
						$id = 'tiny'.rand(1, 1000000);
						$sub = '<script>';
						$sub .= 'tinyMCE.init({mode : "exact", theme : "advanced", elements: "'.$id.'",'.
							'theme_advanced_toolbar_location : "top", '.
							'theme_advanced_toolbar_align : "left"});';
						$sub .= '</script>';
						$sub .= '<textarea id="'.$id.'" name="'.$fullfname.'" rows="15" cols="80" style="width: 100%">';
						$sub .= $fvalue;
						$sub .= '</textarea>';
					}
					
					elseif ($args[0] == 'view') // Адрес ссылки на другой view.
					{
						$sub = '?view='.$fvalue.'&rowid='.$row['id'];
					}

					elseif ($args[0] == 'checkbox') // Флажек.
					{
						// 1. ID контрола. 
						$id = ($args[1]) ? 'id="'.$args[1].'"' : '';
					
						// Добавляется невидимое поле со значением, а JS синхронизирует их.
						$sub = '<input type="hidden" name="'.$fullfname.'" value="'.$fvalue.'" '.$id.'/>';
						$sub .= '<input type="checkbox" ';
						$sub .= $fvalue ? 'checked="checked"' : '';
						$sub .= ' onchange="this.form.elements[\''.$fullfname.'\'].value=this.checked?1:0"/>';
					}
					
					elseif ($args[0] == 'attachment') // Файл.
					{
						// 1. Имя ссылочной таблицы.
						$ctable = mysql_escape_string($args[1]);
						$filter = $this->params['table_name'].';'.$row['id'].';'.$ctable;
						$data = $mvc->db->get_data('SELECT * FROM '.$ctable);
						$sub = "<a href='#' onclick='return open_dialog(\"".$filter."\", \"".$row['id']."\")'>".$fcomment.'</a>';
					}
					
					elseif ($args[0] == 'file') // Файл.
					{
						// 1. Тип (edit,image). // 2. ID контрола.
						$type = ($args[1]) ? $args[1] : 'edit';
						//$id = ($args[2]) ? 'id="'.$args[2].'"' : 'id_'.$fullfname;
						$my_id = 'id_'.$fullfname;
					
						if ($type == 'image')
						{
							$sub = '<input type="hidden" name="'.$fullfname.'" value="'.$fvalue.'" id="'.$my_id.'" />';
							$sub .= '<img src="'.$fvalue.'" id="'.$my_id.'_img" ondblclick="file_selector.run(\'#'.$my_id.'\', this)" >';
						}
						elseif ($type == 'minified')
						{
							$sub = '<input type="hidden" name="'.$fullfname.'" value="'.$fvalue.'" id="'.$my_id.'" />';
							$sub .= '<img src="'.minify($fvalue).'" id="'.$my_id.'_img" ondblclick="file_selector.run(\'#'.$my_id.'\', this)" >';
						}
						else
						{
							// Добавляется невидимое поле со значением, а JS синхронизирует их.
							$sub = '<input name="'.$fullfname.'" value="'.$fvalue.'" id="'.$my_id.'" />';
							$sub .= '<input type="button" onclick="file_selector.run(\'#'.$my_id.'\')" value="...">';
							$sub .= '<input type="button" onclick="jQuery(\'#'.$my_id.'\').val(\'\')" value="X">';
						}						
					}					

					elseif ($args[0] == 'select') // Выбор из другой таблицы.
					{
						// Выбор из другой таблицы.
						// 1. Имя таблицы, 2. Поле со значениями, 3. Поле с надписями. 4. Условие(опция). 5. ID контрола.
						$id = ($args[5]) ? 'id="'.$args[5].'"' : '';

						$args[4] = isset($args[4]) ? $args[4] = 'WHERE '.$args[4] : ''; // Условие.
						$r = $mvc->db->query('SELECT '.$args[2].','.$args[3].' FROM '.$args[1].' '.$args[4].'ORDER BY '.$args[2]);
						$sub = '<select name="'.$fullfname.'" '.$id.'>';
						$sub .= '<option ';
						$sub .= ($fvalue == '') ? 'selected ' : '';
						$sub .= 'value="(none)"></option>';

						while ($a = mysql_fetch_row($r))
						{
							$sub .= '<option ';
							$sub .= ($a[0] == $fvalue) ? 'selected ' : '';
							$sub .= 'value="'.$a[0].'">'.$a[1].'</option>';
						}
						$sub .= '</select>';
						mysql_free_result($r);
					}
					
					elseif ($args[0] == 'select_label') // Выбор из другой таблицы.
					{
						// Выбор из другой таблицы.
						// 1. Имя таблицы, 2. Поле со значениями, 3. Поле с надписями. 4. Условие(опция). 5. ID контрола.
						$id = ($args[5]) ? 'id="'.$args[5].'"' : '';

						$args[4] = isset($args[4]) ? $args[4] = ' AND '.$args[4] : ''; // Условие.
						$tmp_data = $mvc->db->get_data('SELECT '.$args[3].' FROM '.$args[1].' WHERE '.$args[2].' ='.$fvalue.''.$args[4].' ORDER BY '.$args[2]);

						$sub = '';
						foreach($tmp_data as $tmp_row)
							$sub .= $tmp_row[$args[3]].', ';
						$sub = rtrim($sub, ', ');
					}					
					
					elseif ($args[0] == 'multyselect') // Выбор из другого view.
					{
						$id = ($args[5]) ? 'id="'.$args[5].'"' : '';

						$args[4] = isset($args[4]) ? $args[4] = 'WHERE '.$args[4] : ''; // Условие.
						$r = $mvc->db->query('SELECT '.$args[2].','.$args[3].' FROM '.$args[1].' '.$args[4].'ORDER BY '.$args[2]);
						$sub = '<select multiple="multiple" name="'.$fullfname.'[]" '.$id.'>';
						$sub .= '<option ';
						$sub .= ($fvalue == '') ? 'selected ' : '';
						$sub .= 'value="(none)"></option>';

						// Поле содержит id другой таблицы через ,
						$afvalue = array_flip(explode(',', $fvalue));

						//die();
						while ($a = mysql_fetch_row($r))
						{
							$sub .= '<option ';
							$sub .= isset($afvalue[$a[0]]) ? 'selected ' : '';
							$sub .= 'value="'.$a[0].'">'.$a[1].'</option>';
						}
						$sub .= '</select>';
						mysql_free_result($r);						
					}
					
					elseif ($args[0] == 'multyselect_label') // Выбор из другого view.
					{
						$id = ($args[5]) ? 'id="'.$args[5].'"' : '';

						$args[4] = isset($args[4]) ? $args[4] = ' AND '.$args[4] : ''; // Условие.
						$tmp_data = $mvc->db->get_data('SELECT '.$args[3].' FROM '.$args[1].' WHERE '.$args[2].' in ('.$fvalue.')'.$args[4].' ORDER BY '.$args[2]);

						$sub = '';
						foreach($tmp_data as $tmp_row)
							$sub .= $tmp_row[$args[3]].', ';
						$sub = rtrim($sub, ', ');
					}					

					elseif ($args[0] == 'selectview') // Выбор из другого view.
					{
						// Выбор из другого view.
						// 1. Имя view, 2. Поле со значениями, 3. Поле с надписями. 4. ID контрола.
						$id = ($args[4]) ? 'id="'.$args[4].'"' : '';

						$view = new c_storage_controller();
						$view->create($args[1]);
						$sql = $this->parse($view->params['view_sql']);

						$r = $mvc->db->query($sql);
						$sub = '<select name="'.$fullfname.'" ' . $id. '>';
						while ($a = mysql_fetch_assoc($r))
						{
							$sub .= '<option ';
							$sub .= ($a[$args[2]] == $fvalue) ? 'selected ' : '';
							$sub .= 'value="'.$a[$args[2]].'">'.$a[$args[3]].'</option>';
						}
						$sub .= '</select>';
						mysql_free_result($r);
					}

					elseif ($args[0] == 'formheader') // Заголовок формы для отправки данных.
					{
						$get = $this->makeGet();						
						$sub = '<form action="'.$get.'" method="POST" enctype="multipart/form-data">';
						$sub .= '<input type="hidden" name="view" value="'.$this->params['id'].'" />';
						$sub .= '<input type="hidden" name="cmd" value="set" />';
					}

					elseif ($args[0] == 'hash') // ХЕШ - иммитация условия.
					{
						// 1. Ключ, 2. Набор вариантов разделнные запятой, 3. Набор действий разделнные запятой.
						$keys = array_flip(explode(',', $args[2]));
						$values = explode(',', $args[3]);
						if ($fname)
							$args[1] = $fvalue;
							
						if (array_key_exists($args[1], $keys))
							$sub = $values[$keys[$args[1]]];							
						elseif (array_key_exists('*', $keys))
							$sub = $values[$keys['*']];
						else
							$sub = '';
					}
					
					elseif ($args[0] == 'href') // Системная ссылка.
					{
						// 1. Тип (del - удалить, back - назад, set - копировать).
						// 2. Имена параметров через , .
						// 3. Значения параметров через , .
												
						if ($args[1] == '')
						{
							$names = explode(',', $args[2]);
							$vals = explode(',', $args[3]);
							$get_params = array();
							for($i2 = 0; $i2 < sizeof($names); $i2++)
								$get_params[$names[$i2]] = $vals[$i2];
							
							$sub = ''.$this->makeGet($get_params);
						}
						else
						{
							$get_params = array('view' => $this->params['id'], 'cmd' => $args[1]);
							if (($args[1] == 'del') || ($args[1] == 'set'))
								$get_params['_checked_'.$row['id']] = 1;
							
							//$sub = '?'.$this->makeGet().'view='.$this->params['view_id'].'&cmd='.$args[1];
							$sub = ''.$this->makeGet($get_params);
						}
					}	
					
					elseif ($args[0] == '_checked') // Системный checkbox для отметки элементов для удаления.
					{
						// 1. ID контрола. 
						$id = ($args[1]) ? 'id="'.$args[1].'"' : '';

						$item_name = '_checked_'.$row['id'];
						$sub = '<input type="hidden" name="'.$item_name.'" value="0" '.$id.'/>';
						$sub .= '<input type="checkbox" onchange="this.form.elements[\''.$item_name.'\'].value=this.checked?1:0"/>';
					}	

					elseif ($args[0] == 'paging') // Установить количество элементов на странице.
					{
						// 1. Количество элементов в на странице. Если 0, то разбиение выключено.
						$this->page_size = (int)$args[1];
						$sub = '';
					}

					elseif ($args[0] == 'pages') // Вывод страниц.
					{
						// 1. Количество элементов в листалке (номеров страницы).
						$sub = $this->render_pages((int)$args[1]);
					}
					
					elseif ($args[0] == 'keepget') // Вывод страниц.
					{
						// 1. Имена сохраняемых GET-параметров через запятую.
						$args[1] = str_replace('page$uid', 'page'.$uid, $args[1]);
						$this->keep_get .= ';'.str_replace(',', ';', $args[1]);
						$sub = '';//$this->keep_get;
					}

					elseif ($args[0] == 'btn') // Системная кнопка submit.
					{
						// 1. Тип кнопки (set, back, copy, del). 2. Надпись. 3. ID контрола. 
						$id = ($args[3]) ? 'id="'.$args[3].'"' : '';

						$sub = '<input type="submit" onmousedown="this.form.elements[\'cmd\'].value=\''.$args[1].'\'" name="_cmd'.$args[1].'" value="'.$args[2].'" '.$id.'/>';
					}
					
					elseif ($args[0] == 'G') // Параметр GET-запроса.
					{
						// 1. Имя параметра. Если пода $, то формирует полную строку get без ?
						// 2. Значение по умолчанию.
						$sub = isset($_GET[$args[1]]) ? $_GET[$args[1]] : $args[2];
					}		

					elseif ($args[0] == 'P') // Параметр POST-запроса.
					{
						// 1. Имя параметра.
						$sub = isset($_POST[$args[1]]) ?  $_POST[$args[1]] : '';
					}		

					elseif ($args[0] == 'R') // Параметр REQUEST-запроса.
					{
						// 1. Имя параметра.
						$sub = isset($this->args[$args[1]]) ?  $this->args[$args[1]] : '';
					}
					
					elseif ($args[0] == 'datatype') // Выбор из спсика типов данных.
					{
						$types = array('int', 'float', 'string', 'text');
						$sub = '<select name="'.$fullfname.'" '.$id.'>';
						foreach($types as $k => $v)
						{
							$selected = '';
							if ($v == $fvalue) $selected = 'selected';
							$sub .= '<option value="'.$v.'" '.$selected.'>'.$v.'</option>';
						}
						$sub .= '</select>';
					}								

					elseif ($args[0] == 'systemicon') // Системная иконка путь к файл у в папке иконок темы.
					{
						$sub = $modx->config['base_url'].'manager/media/style/'.$modx->config['manager_theme'].'/images/icons/'.$args[1];
						$sub = '<img src="'.$sub.'">';
					}
					

					else // Не опознанная вставка, оставим без изменений.
					{
						$sub = '{'.$sub.'}';
					}
				}
				else
				// Не опознанная вставка, оставим без изменений.
				{
					$sub = '{'.$sub.'}';
				}
				
				// Заменим найденное значение ссылкой, чтобы не заменять параметры внутри него.
				{
					$key = '(_%ROW'.$nextvar++.'%_)';
					$vars[$key] = $sub;
					$sub = $key;
				}
				
				$tpl = substr($tpl, 0, $i).$sub.substr($tpl, $j + 1);
				$j = $i;
			}
			
			// Вставка найденных переменных.
			$vars = array_reverse($vars);
			foreach ($vars as $k=>$v)
				$tpl = str_replace($k, $v, $tpl);

			return $tpl;//stripslashes($tpl);
		}
		
		
		function makeGet($params = NULL)
		{
			$get = array();
			
			// Перенесем требуемые параметры.
			$keep = explode(';', $this->keep_get);
			foreach($keep as $k => $v)
			{
				if (isset($_GET[$v])) $get[$v] = $_GET[$v];
			}

			// Добавим поданые папаметры.
			if ($params)
			{
				foreach($params as $k => $v)
					$get[$k] = $v;
			}			

			// Формируем ссылку.
			$url = '';			
			foreach($get as $k => $v)
				$url .= $k.'='.$v.'&';

			return $this->base_url.'?'.trim($url, '&');
		}
		
		// Количество записей в данном view.
		function get_records_count()
		{
			global $mvc;
			
			$sql = $this->parse($this->params['view_sql']);
			//$sql = $this->sql;
			$sql_lower = strtolower($sql);
			$i1 = strpos($sql_lower, 'select');
			$i2 = strpos($sql_lower, 'from');
			$sql = substr($sql, 0, $i1 + 6).' count(*) '.substr($sql, $i2);

			$r = $mvc->db->query($sql);
			$a = mysql_fetch_row($r);
			mysql_free_result($r);
			return (int)$a[0];
		}
		
		// Количество страницы в данном view.
		function pages_count()
		{
			if ($this->page_size > 0)
				return (int)ceil($this->get_records_count() / $this->page_size);
			else
				return 0;
		}
		
		// Получить массив с номерами страниц данного view(исходя из настроек).
		function get_pages()
		{
			$page = $this->page;
			$pages_count = $this->pages_count();
			$render_count_2 = (int)($render_count / 2);
			$render_count = $render_count_2 * 2 + 1; // Страниц всегде нечетное число.

			// Начальная страница = 0, если близко к началу, иначе = (страница - кол-во отрисованных).
			$first_page = $page - $render_count_2;
			$first_page = max($first_page, 0);
			
			// Конечная страница = кол-во страниц, если близки к концу, иначе = (последняя - )
			$last_page = $page + $render_count_2 + 1;
			$last_page = min($last_page, $pages_count);
			
			// Смещение левой границы, если номеров не хватает до $render_count.
			$delta = $render_count - ($last_page - $first_page);
			if ($delta > 0)
				$first_page = max($first_page - $delta, 0);
				
			// Смещение правой границы, если номеров не хватает до $render_count
			$delta = $render_count - ($last_page - $first_page);
			if ($delta > 0)
				$last_page = min($last_page + $delta, $pages_count);
			
			$pagename = 'page'.$this->params['uid'];
			$url = '?'.$this->makeGet(array('view' => $this->params['id'])).'&'.$pagename.'=';
			
			$data = array();
			for ($i = $first_page; $i < $last_page; $i++)
			{
				$row = array('page0' => $i, 'page1' => $i + 1, 'href' => $url.$i, 'active' => ($page == $i));
				if ($i == $page)
					$row['link'] = '<a class="active">'.($i + 1).'</a>';
				else
					$row['link'] = '<a href="'.$url.$i.'">'.($i + 1).'</a>';
			}
			
			return $data;
		}
		
		function render_pages($render_count)
		{
			$page = $this->page;
			$pages_count = $this->pages_count();
			$render_count_2 = (int)($render_count / 2);
			$render_count = $render_count_2 * 2 + 1; // Страниц всегде нечетное число.

			// Начальная страница = 0, если близко к началу, иначе = (страница - кол-во отрисованных).
			$first_page = $page - $render_count_2;
			$first_page = max($first_page, 0);
			
			// Конечная страница = кол-во страниц, если близки к концу, иначе = (последняя - )
			$last_page = $page + $render_count_2 + 1;
			$last_page = min($last_page, $pages_count);
			
			// Смещение левой границы, если номеров не хватает до $render_count.
			$delta = $render_count - ($last_page - $first_page);
			if ($delta > 0)
				$first_page = max($first_page - $delta, 0);
				
			// Смещение правой границы, если номеров не хватает до $render_count
			$delta = $render_count - ($last_page - $first_page);
			if ($delta > 0)
				$last_page = min($last_page + $delta, $pages_count);

			$pagename = 'page'.$this->params['uid'];			

			$url = ''.$this->makeGet(array('view' => $this->params['id'])).'&'.$pagename.'=';
			
			$html = '<style>';
			$html .= '.pager a{display:block; width:30px; border:1px #ddd solid; text-align:center}';
			$html .= '.pager .active{background: #ccc; font-weight:bold; font-size:24px}';
			$html .= '</style>';
			$html .= '<table class="pager"><tr>';
			
			for ($i = $first_page; $i < $last_page; $i++)
			{
				if ($i == $page)
					$html .= '<td><a class="active">'.($i + 1).'</a></td>';
				else
					$html .= '<td><a href="'.$url.$i.'">'.($i + 1).'</a></td>';
			}
			
			$html .= '</tr></table>';
			
			return $html;
		}

		function _create_view_list($table_name)
		{
			global $mvc;

			$table = new c_table_model($table_name);

			$view_data = array('table_name' => $table_name);
			$view_data['view_name'] = $table_name.'_list';
			$view_data['view_title'] = $table->comment;
			$view_data['view_sql'] = 'SELECT * FROM '.$table_name;
			$view_data['prev_view'] = 'user_views';
			$view_data['next_view'] = $view_data['view_name'];
			$view_data['visible'] = 1;

			$header = '{:keepget;page$uid}{:paging;20}{:formheader}<center>';
			$header .= '{view_title}<table border="1" cellspacing="0"><tr><td> </td>'."\r\n";
			$row = '<tr onmouseover="this.style.background=\'#ddd\'" onmouseout="this.style.background=\'\'" >';
			$row .= '<td>{:_checked}</td>';

			$footer = '<tr><td colspan="100" align="center">'."\n";
			$footer .= '{:btn;set;Сохранить}{:btn;back;Отмена}{:btn;del;Удалить}</td></tr></table>'."\n";
			$footer .= '{:pages;9}<center></form>'."\n";

			$fields = $mvc->db->get_fields($table_name);
			foreach ($fields as $k => $v)
			{
				$header .= '<th>{'.$k.':comment}</th>'."\n";
				
				$type = '';
				if ($table->fields[$k]['type'] == 'int')
				{
					if (substr($k, strlen($k) - 3) == '_id')
					{
						$type = ':select_label;'.substr($k, 0, strlen($k) - 3).';id;name';
					}
				}
				$row .= '<td>{'.$k.$type.'}</td>'."\n";
			}

			$header .= '<th><a href="{:href;;view;'.$table_name.'_item}" return confirm("Are you sure?")>A</a></th>'."\n";
			$header .= '</tr>'."\n";
			$row .= '<th><a href="{:href;;view,rowid;'.$table_name.'_item,{id}}">E</a>'."\n";
			$row .= '<a href="{:href;del}">X</a></th></tr>';

			$view_data['tpl'] = $header."\n{eachrow}\n".$row."\n{/eachrow}\n\n".$footer;

			$mvc->db->set_row($mvc->config['dbpref'].'views', $view_data);
		}

		function _create_view_item($table_name)
		{
			global $mvc;
			
			$table = new c_table_model($table_name);
			
			$view_data = array('table_name' => $table_name);
			$view_data['view_name'] = $table_name.'_item';
			$view_data['view_title'] =  $table->comment;
			$view_data['view_sql'] = 'SELECT * FROM '.$table_name.' WHERE id={rowid}';
			$view_data['prev_view'] = $table_name.'_list';
			$view_data['next_view'] = $table_name.'_list';
			$view_data['allow_empty'] = 1;
			$view_data['visible'] = 0;

			$view_data['tpl'] = '{:keepget;page$uid}{:formheader}<center>{view_title}<table border="1" cellspacing="0">'."\n";
			$view_data['tpl'] .= '{eachrow}'."\n";
			$fields = $mvc->db->get_fields($table_name);
			foreach ($fields as $k => $v)
			{
				if ($k == 'id')
					$view_data['tpl'] .= '<tr><th>'.$k.'</th><td>{'.$k.':label}</td></tr>'."\n";
				else
				{
					$type = 'edit';
					if ($table->fields[$k]['type'] == 'date')
					{
						$type = 'datepicker';
					}
					elseif ($table->fields[$k]['type'] == 'int')
					{
						if (substr($k, strlen($k) - 3) == '_id')
						{
							$type = 'select;'.substr($k, 0, strlen($k) - 3).';id;name';
						}
					}					
					
					$view_data['tpl'] .= '<tr><th>{'.$k.':comment}</th><td>{'.$k.':'.$type.'}</td></tr>'."\n";
				}
				
			}
			$view_data['tpl'] .= '{/eachrow}'."\n";
			$view_data['tpl'] .= '<tr><td colspan="100" align="center">{:btn;set;Сохранить}{:btn;back;Отмена}</td></tr>'."\n";
			$view_data['tpl'] .= '</table></center></form>'."\n";

			$mvc->db->set_row($mvc->config['dbpref'].'views', $view_data);
		}

// ==========================  Вставлено из mvc_view =======================
		
		// Выбрать из массива $source, данные для полей $fields.
		function extract_data($source, $fields)
		{
			//print_ r(array_intersect_key($this->args, $ar2));
		
			$fields['_checked'] = true; // Среди полей будем искать системное _checked.
			$data = array();
			foreach($source as $k => $v)
			{
				// Формат имени поля name_id
				$i = strrpos($k, '_');
				if ($i !== false) // Возможно это поле.
				{
					$fname = substr($k, 0, $i);
					$fid = (int)substr($k, $i + 1);

					if (array_key_exists($fname, $fields)) // Это имя есть в списке полей.
					{
						//echo '<font color="red">'.(int)$fid.' '.$fname.'</font><br>';
						if (!array_key_exists($fid, $data)) $data[$fid] = array('id' => $fid);
						$data[$fid][$fname] = $v; 						
					}					
				}
			}
			return $data;
		}	
		
		// -------------------------------- other
		// Получить список хранилищ. $fields - список полей.
		function get_list($fields = '*')
		{
			global $mvc;
			$sql = $mvc->parse('SELECT view_name, '.$fields.' FROM {dbpref}views');
			$data = $mvc->db->get_data($sql);
			$res = array();
			foreach($data as $k => $row)
			{
				$res[$row['view_name']] = $row;
			} 
			return $res;
		}		
	}
?>